package hibernate.method;

import hibernate.method.interfaces.GameCategoryInterface;
import hibernate.model.Category;
import hibernate.model.Game;
import hibernate.model.GameCategory;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.LogicalExpression;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;

public class GameCategoryMethods implements GameCategoryInterface{

	@Override
	public void addCategoryToGame(SessionFactory sessionFactory,
			Session session, int game_id, int category_id) {
		GameCategory gcat= new GameCategory();
		gcat.setGame_id(game_id);
		gcat.setCategory_id(category_id);
		session.save(gcat);
		
	}

	@Override
	public void deleteCategoryFromGame(SessionFactory sessionFactory,
			Session session, GameCategory gamecat) {
		session.delete(gamecat);
		
	}

	@Override
	public GameCategory findGameCategory(SessionFactory sessionFactory,
			Session session, int game_id, int category_id) {
		Criteria cr = session.createCriteria(GameCategory.class);
		Criterion game = Restrictions.eq("game_id", game_id);
		Criterion category = Restrictions.eq("category_id", category_id);
	
		LogicalExpression andExp = Restrictions.and(game, category);
		cr.add(andExp);
		
		return (GameCategory) cr.list().get(0);
	}

	@Override
	public Integer countByCategory(SessionFactory sessionFactory,
			Session session, int category_id) {
		Criteria cr = session.createCriteria(GameCategory.class);
		cr.add(Restrictions.eq("category_id", category_id));
		return ((Number)cr.setProjection(Projections.rowCount()).uniqueResult()).intValue();
	}

	@Override
	public Integer countByGame(SessionFactory sessionFactory, Session session,
			int game_id) {
		Criteria cr = session.createCriteria(GameCategory.class);
		cr.add(Restrictions.eq("game_id", game_id));
		return ((Number)cr.setProjection(Projections.rowCount()).uniqueResult()).intValue();

	}

	@SuppressWarnings("unchecked")
	@Override
	public List<GameCategory> listByCategory(SessionFactory sessionFactory,
			Session session, int category_id) {
		Criteria cr = session.createCriteria(GameCategory.class);
		Criterion category = Restrictions.eq("category_id", category_id);
		cr.add(category);
		return cr.list();
	}



	@Override
	public List<Game> listGamesByCategory(SessionFactory sessionFactory,
			Session session, List<GameCategory> gamecat) {
	List<Game> games = new ArrayList<Game>();
	GameMethods gm = new GameMethods();
		for (GameCategory gc : gamecat){
			games.add(gm.idToGame(sessionFactory, session, gc.getGame_id()));
		}
		return games;
	}

	@Override
	public List<Game> listGamesWithoutThisCategory(
			SessionFactory sessionFactory, Session session, int category_id) {
		Criteria cr = session.createCriteria(GameCategory.class);
		Criterion category = Restrictions.neOrIsNotNull("category_id", category_id);
		cr.add(category);
		@SuppressWarnings("unchecked")
		List<GameCategory> gamecat = cr.list();
		List<Game> games = new ArrayList<Game>();
		GameMethods gm = new GameMethods();
			for (GameCategory gc : gamecat){
				games.add(gm.idToGame(sessionFactory, session, gc.getGame_id()));
			}
			return games;
	}

	@Override
	public List<String> listCategoriesByGame(SessionFactory sessionFactory,
			Session session, int game_id) {
		Criteria cr = session.createCriteria(GameCategory.class);
		Criterion game = Restrictions.eq("game_id", game_id);
		cr.add(game);
		@SuppressWarnings("unchecked")
		List<GameCategory> gamecat = cr.list();
		//System.out.println("gamecat: "+ gamecat.get(0).getId());
		if (gamecat.isEmpty()) return null;
		List<String> categories = new ArrayList<String>();
		CategoryMethods cat = new CategoryMethods();
			for (GameCategory gc : gamecat){
				Category c = cat.idToCategory(sessionFactory, session, gc.getCategory_id());
				categories.add(c.getCategory());
			}
			HashSet<String> hs = new HashSet<String>();
			hs.addAll(categories);
			categories.clear();
			categories.addAll(hs);
			
			return categories;
	}

	@Override
	public List<String> listUnusedGameByCategory(SessionFactory sessionFactory,
			Session session, int category_id) {
		GameMethods gamem = new GameMethods();
		List <Game> allGames = gamem.listAllGames(sessionFactory, session);
		List<GameCategory> gamesInCategory = listByCategory(sessionFactory, session, category_id);
		List<String> GamesIds = new ArrayList<String>();
		List<String> Games = new ArrayList<String>();
		for(Game g1 : allGames){
			GamesIds.add(String.valueOf(g1.getGame_id()));
		}
		for (GameCategory g2:gamesInCategory){
			GamesIds.remove(String.valueOf(g2.getGame_id()));
		}
		for (String i:GamesIds){
			Game g = gamem.idToGame(sessionFactory, session, Integer.parseInt(i));
			Games.add(g.getName());
		}
		return Games;
	}

	@SuppressWarnings("unchecked")
	@Override
	public void deleteGameFromGamesCategories(SessionFactory sessionFactory,
			Session session, int game_id) {
		Criteria cr = session.createCriteria(GameCategory.class);
		Criterion category = Restrictions.eq("game_id", game_id);
		cr.add(category);
		List<GameCategory> gcat = new ArrayList<GameCategory>(cr.list());
		for (GameCategory gc:gcat){
			session.delete(gc);
		}
		
	}

	
	
	
	
}
